package com.bit101.components {
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	[Event(name="change",type="flash.events.Event")]
	public class Slider extends Component {
		protected var _handle:Sprite;
		protected var _back:Sprite;
		protected var _backClick:Boolean = true;
		protected var _value:Number = 0;
		protected var _max:Number = 100;
		protected var _min:Number = 0;
		
		protected var _orientation:String;  //方向
		protected var _tick:Number = 0.01;  //百分比
		public static const HORIZONTAL:String = "horizontal";
		public static const VERTICAL:String = "vertical";

		/**
		 * 滑块基类
		 * 
		 */		
		public function Slider(orientation:String = Slider.HORIZONTAL, parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, defaultHandler:Function = null){
			_orientation = orientation;
			super(parent, xpos, ypos);
			
			if (defaultHandler != null){
				addEventListener(Event.CHANGE, defaultHandler);
			}
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void {
			super.init();
			if (_orientation == HORIZONTAL){
				setSize(100, 10);  //水平滑块
			} else {
				setSize(10, 100);  //竖型滑块
			}
		}

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void {
			super.draw();
			drawBack();
			drawHandle();
		}
		/**
		 * 添加滑块及底
		 */
		override protected function addChildren():void {
			_back = new Sprite();
			_back.filters = [getShadow(2, true)];
			addChild(_back);
			
			_handle = new Sprite();
			_handle.filters = [getShadow(1)];
			_handle.addEventListener(MouseEvent.MOUSE_DOWN, onDrag); //鼠标按下
			_handle.buttonMode = true;
			_handle.useHandCursor = true;
			addChild(_handle);
		}
		
		/**
		 * 绘制底
		 * 侦听鼠标按下事件
		 */
		protected function drawBack():void {
			_back.graphics.clear();
			_back.graphics.beginFill(Style.BACKGROUND);
			_back.graphics.drawRect(0, 0, _width, _height);
			_back.graphics.endFill();
			//底是否支持滚动
			if (_backClick){
				_back.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
			} else {
				_back.removeEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
			}
		}

		/**
		 * 绘制滑块
		 * 区分水平与竖型8 8
		 */
		protected function drawHandle():void {
			_handle.graphics.clear();
			_handle.graphics.beginFill(Style.BUTTON_FACE);
			if (_orientation == HORIZONTAL){
				_handle.graphics.drawRect(1, 1, _height -2, _height - 2);
			} else {
				_handle.graphics.drawRect(1, 1, _width - 2, _width - 2);
			}
			_handle.graphics.endFill();
			positionHandle();
		}

		/**
		 * value初始值 0
		 * max  100
		 * min  0
		 */
		protected function correctValue():void {
			if (_max > _min){
				_value = Math.min(_value, _max);
				_value = Math.max(_value, _min); //100
			} else {
				_value = Math.max(_value, _max);
				_value = Math.min(_value, _min);
			}
		}


		/**
		 * 设置滑块参数
		 * @param min 滑动最小值.
		 * @param max 滑动最大值.
		 * @param value 滑动值.
		 */
		public function setSliderParams(min:Number, max:Number, value:Number):void {
			this.minimum = min;
			this.maximum = max;
			this.value = value;
		}

		/**
		 * 设置滑块坐标
		 * 百分比乘总长度  x = value/main * range
		 */
		protected function positionHandle():void {
			var range:Number;
			if (_orientation == HORIZONTAL){
				range = _width - _height;
				_handle.x = (_value - _min) / (_max - _min) * range;
			} else {
				range = _height - _width;
				_handle.y = (_value - _min) / (_max - _min) * range;	
			}
		}
		
		/**
		 * 点击底计算滑块坐标及value值
		 * 先确定滑块的坐标
		 * _value = _handle.y
		 * @param event
		 */
		protected function onBackClick(event:MouseEvent):void {
			if (_orientation == HORIZONTAL){
				_handle.x = mouseX - _height / 2;
				_handle.x = Math.max(_handle.x, 0);
				_handle.x = Math.min(_handle.x, _width - _height);
				_value = _handle.x / (width - _height) * (_max - _min) + _min;
			} else {
				_handle.y = mouseY - _width / 2;   //拖动是否滑块的1/2
				_handle.y = Math.max(_handle.y, 0);//最大值不超过范围
				_handle.y = Math.min(_handle.y, _height - _width);
				
				//_value = (_height - _width _handle.y) / (height - _width) * (_max - _min) + _min;
				_value =  _handle.y / (height - _width) * (_max - _min) + _min;
			}
			dispatchEvent(new Event(Event.CHANGE));
		}

		/**
		 * 拖动滑块，拖动范围
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onDrag(event:MouseEvent):void {
			stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onSlide);
			if (_orientation == HORIZONTAL){
				_handle.startDrag(false, new Rectangle(0, 0, _width - _height, 0));
			} else {
				_handle.startDrag(false, new Rectangle(0, 0, 0, _height - _width));
			}
		}

		/**
		 * 舞台释放，停止拖动
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onDrop(event:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onSlide);
			stopDrag();
		}

		/**
		 * 侦听移动事件
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onSlide(event:MouseEvent):void {
			var oldValue:Number = _value;
			if (_orientation == HORIZONTAL){
				_value = _handle.x / (width - _height) * (_max - _min) + _min;
			} else {
				//_value = (_height - _width - _handle.y) / (height - _width) * (_max - _min) + _min;
				_value = (_handle.y) / (height - _width) * (_max - _min) + _min;
			}
			
			if (_value != oldValue){
				dispatchEvent(new Event(Event.CHANGE));
			}
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////
		/**
		 * 设置底是否支持点击
		 */
		public function set backClick(b:Boolean):void {
			_backClick = b;
			invalidate();
		}

		public function get backClick():Boolean {
			return _backClick;
		}

		/**
		 * Sets / gets 设置当前滑块的值.
		 * 滑块的坐标
		 */
		public function set value(v:Number):void {
			_value = v;
			correctValue();
			positionHandle();
		}

		/**精确两位小数点，*/
		public function get value():Number {
			//_value = Math.floor(_value);
			return Math.round(_value / _tick) * _tick;
		}

		/**
		 * value的精确值
		 */
		public function get rawValue():Number {
			return _value;
		}

		/**
		 * 设置最大值
		 * Gets / sets the maximum value of this slider.
		 */
		public function set maximum(m:Number):void {
			_max = m;
			correctValue();
			positionHandle();
		}

		public function get maximum():Number {
			return _max;
		}

		/**
		 * Gets / sets the minimum value of this slider.
		 */
		public function set minimum(m:Number):void {
			_min = m;
			correctValue();
			positionHandle();
		}

		public function get minimum():Number {
			return _min;
		}

		/**
		 * Gets / sets the tick value of this slider. This round the value to the nearest multiple of this number.
		 */
		public function set tick(t:Number):void {
			_tick = t;
		}

		public function get tick():Number {
			return _tick;
		}
	}
}